Crate r0 [−] [src]
Initialization code ("crt0") written in Rust
This is for bare metal systems where there is no ELF loader or OS to take care of initializing RAM for the program.
Initializing RAM
On the linker script side, we must assign names (symbols) to the boundaries
of the .bss
and .data
sections.
.bss : ALIGN(4)
{
_sbss = .;
*(.bss.*);
_ebss = ALIGN(4);
} > RAM
.data : ALIGN(4)
{
_sdata = .;
*(.data.*);
_edata = ALIGN(4);
} > RAM AT > FLASH
_sidata = LOADADDR(.data);
On the Rust side, we must bind to those symbols using an extern
block.
unsafe fn before_main() { // The type, `u32`, indicates that the memory is 4-byte aligned extern "C" { static mut _sbss: u32; static mut _ebss: u32; static mut _sdata: u32; static mut _edata: u32; static _sidata: u32; } zero_bss(&mut _sbss, &mut _ebss); init_data(&mut _sdata, &mut _edata, &_sidata); }
.init_array
& .pre_init_array
This crate also provides an API to add "life before main" functionality to bare metal systems.
On the linker script side, instruct the linker to keep the .init_array
sections from input object files. Store the start and end address of the
merged .init_array
section.
.text :
{
/* .. */
_init_array_start = ALIGN(4);
KEEP(*(.init_array));
_init_array_end = ALIGN(4);
/* .. */
}
On the startup code, invoke the run_init_array
function before you call
the user main
.
unsafe fn start() { extern "C" { static _init_array_start: extern "C" fn(); static _init_array_end: extern "C" fn(); } ::r0::run_init_array(&_init_array_start, &_init_array_end); extern "C" { fn main(argc: isize, argv: *const *const u8) -> isize; } main(); }
Then the user application can use this crate init_array!
macro to run code
before main
.
init_array!(before_main, { println!("Hello"); }); fn main() { println!("World"); }
Macros
init_array | |
pre_init_array |
Functions
init_data⚠ |
Initializes the |
run_init_array⚠ | |
zero_bss⚠ |
Zeroes the |